/**
  ******************************************************************************
  * File Name          : RTC.c
  * Description        : This file provides code for the configuration
  *                      of the RTC instances.
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2019 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "rtc.h"
#include "usart.h"
#include "gpio.h"
#include "cmsis_os.h"
#include "mqttclient.h"
#include "oled_i2c.h"
#include <string.h>
/* USER CODE BEGIN 0 */
extern void action(uint8_t arg);
uint8_t alarmmem[36];
uint8_t setting[14];
/* USER CODE END 0 */

RTC_HandleTypeDef hrtc;
static FLASH_EraseInitTypeDef EraseInitStruct;
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef DateToUpdate = {0};
TimeandDate TD={0};
void MX_RTC_Init(void)
{

	flash_read(0,alarmmem,36);
	flash_read(36,setting,14);
  /**Initialize RTC Only 
  */
  hrtc.Instance = RTC;
  hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
  hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */
    if(HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR1)!=0x5051)
		{
  /* USER CODE END Check_RTC_BKUP */

  /**Initialize RTC and set the Time and Date 
  */
  sTime.Hours = 0x13;
  sTime.Minutes = 0x00;
  sTime.Seconds = 0x00;

  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
		
    Error_Handler();
  }
  DateToUpdate.WeekDay = RTC_WEEKDAY_FRIDAY;
  DateToUpdate.Month = RTC_MONTH_MAY;
  DateToUpdate.Date = 0x10;
  DateToUpdate.Year = 0x19;

  if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK)
  {
		
    Error_Handler();
  }
	
	//__HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC);
	
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR1,0X5051);
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR2,(uint16_t)DateToUpdate.Year);
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR3,(uint16_t)DateToUpdate.Month);
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR4,(uint16_t)DateToUpdate.Date);
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR5,(uint16_t)DateToUpdate.WeekDay);
	
}else
		{
			DateToUpdate.Year=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR2);
			DateToUpdate.Month=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR3);
			DateToUpdate.Date=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR4);
			DateToUpdate.WeekDay=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR5);
			HAL_RTC_SetDate(&hrtc,&DateToUpdate,RTC_FORMAT_BCD);
			__HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC);
			
		}
		
}

void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{

  if(rtcHandle->Instance==RTC)
  {
  /* USER CODE BEGIN RTC_MspInit 0 */

  /* USER CODE END RTC_MspInit 0 */
    HAL_PWR_EnableBkUpAccess();
    /* Enable BKP CLK enable for backup registers */
    __HAL_RCC_BKP_CLK_ENABLE();
		__HAL_RCC_PWR_CLK_ENABLE();
    /* RTC clock enable */
    __HAL_RCC_RTC_ENABLE();

    /* RTC interrupt Init */
//    HAL_NVIC_SetPriority(RTC_IRQn, 5, 0);
//    HAL_NVIC_EnableIRQ(RTC_IRQn);
  /* USER CODE BEGIN RTC_MspInit 1 */

  /* USER CODE END RTC_MspInit 1 */
  }
}

void HAL_RTC_MspDeInit(RTC_HandleTypeDef* rtcHandle)
{

  if(rtcHandle->Instance==RTC)
  {
  /* USER CODE BEGIN RTC_MspDeInit 0 */

  /* USER CODE END RTC_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_RTC_DISABLE();

    /* RTC interrupt Deinit */
    HAL_NVIC_DisableIRQ(RTC_IRQn);
  /* USER CODE BEGIN RTC_MspDeInit 1 */

  /* USER CODE END RTC_MspDeInit 1 */
  }
} 

void getRealTime(TimeandDate *TD)
{
	
	RTC_TimeTypeDef timebuff;
	RTC_DateTypeDef datebuff;
	HAL_RTC_GetTime(&hrtc,&timebuff,RTC_FORMAT_BCD);
	HAL_RTC_GetDate(&hrtc,&datebuff,RTC_FORMAT_BCD);
	
	BCDtoAscall(timebuff.Hours,TD->hour);
	BCDtoAscall(timebuff.Minutes,TD->minute);
	BCDtoAscall(timebuff.Seconds,TD->second);
	BCDtoAscall(datebuff.Date,TD->day);
	BCDtoAscall(datebuff.Month,TD->month);
	BCDtoAscall(datebuff.Year,TD->year);
	
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR2,(uint16_t)datebuff.Year);
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR3,(uint16_t)datebuff.Month);
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR4,(uint16_t)datebuff.Date);
	HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR5,(uint16_t)datebuff.WeekDay);
}

void BCDtoAscall(uint8_t bcd,uint8_t *td)
{
	unsigned char sAscii[] = "0123456789ABCDEF";
	td[0]=sAscii[(bcd >> 4)];
	td[1]=sAscii[(bcd & 0x0F)];
}

void AscalltoBCD(uint8_t *datain,uint8_t len,uint8_t *dataout)
{
	for(uint8_t i=0;i<len;i+=2)
	{
		dataout[i/2]=(datain[i]<<4)|(datain[i+1]&0x0f);
	}
}
	

void setalarm(uint8_t *v1)
{
	uint8_t j;
	if(v1[0]==0x30)
	{
		switch (v1[1])
		{
			case 0x30:
				for(j=0;j<16;j++){
					alarmmem[j]=0x00;
				}
					break;
			case 0x31:
				for(j=0;j<4;j++){
					alarmmem[j]=v1[j+2];
				}
				for(j=0;j<12;j++){
					alarmmem[j+4]=0x00;
				}
				break;
			case 0x32:
				for(j=0;j<8;j++){
					alarmmem[j]=v1[j+2];
				}
				for(j=0;j<8;j++){
					alarmmem[j+8]=0x00;
				}
				break;
			case 0x33:
				for(j=0;j<12;j++){
					alarmmem[j]=v1[j+2];
				}
				for(j=0;j<4;j++){
					alarmmem[j+12]=0x00;
				}
				break;
			case 0x34:
				for(j=0;j<16;j++){
					alarmmem[j]=v1[j+2];
				}
				break;
			default:
				break;
		}
	}else if(v1[0]==0x31){
		switch (v1[1])
		{
			case 0x30:
				for(j=0;j<16;j++){
					alarmmem[j+16]=0x00;
				}
					break;
			case 0x31:
				for(j=0;j<4;j++){
					alarmmem[j+16]=v1[j+2];
				}
				for(j=0;j<12;j++){
					alarmmem[j+20]=0x00;
				}
				break;
			case 0x32:
				for(j=0;j<8;j++){
					alarmmem[j+16]=v1[j+2];
				}
				for(j=0;j<8;j++){
					alarmmem[j+24]=0x00;
				}
				break;
			case 0x33:
				for(j=0;j<12;j++){
					alarmmem[j+16]=v1[j+2];
				}
				for(j=0;j<4;j++){
					alarmmem[j+28]=0x00;
				}
				break;
			case 0x34:
				for(j=0;j<16;j++){
					alarmmem[j+16]=v1[j+2];
				}
				break;
			default:
				break;
		}
	}else if(v1[0]==0x32){
		for(j=0;j<4;j++){
			alarmmem[j+32]=v1[j+1];}
		}	

}

void event1(void){
	action(1);			
}
void event2(void){
	action(2);
}
void event3(void){
	action(4);
}
/* USER CODE BEGIN 1 */
//void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc)
void RTC_Callback(void const * argument)
{
		uint8_t g;
		
		getRealTime(&TD);
		
		for(g=0;g<9;g++)
		{
			if((TD.hour[0]-alarmmem[g*4]==0)&&(TD.hour[1]-alarmmem[g*4+1]==0)){
				if((TD.minute[0]-alarmmem[g*4+2]==0)&&(TD.minute[1]-alarmmem[g*4+3]==0)){
					if((TD.second[0]==0X30)&&(TD.second[1]==0X30)){
						if(g<4){
							event1();}
						else if(g<8){
							event2();}
						else if(g<9){
							event3();}
					}
				}
			}
		}
		//HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_0);
		uint8_t tx1[]={0X32,0X30,TD.year[0],TD.year[1],0X2D,TD.month[0],TD.month[1],0X2D,TD.day[0],TD.day[1],'\0'};
		uint8_t tx2[]={0X20,TD.hour[0],TD.hour[1],0X3A,TD.minute[0],TD.minute[1],0X3A,TD.second[0],TD.second[1],'\0'};
		OLED_ShowStr(0,0,tx1,2);
		OLED_ShowStr(0,2,tx2,2);
	
}

void settime(uint8_t *rx)
{
	uint8_t tmp1[6];
	AscalltoBCD(rx,12,tmp1);
	DateToUpdate.Year=tmp1[0];
	DateToUpdate.Month=tmp1[1];
	DateToUpdate.Date=tmp1[2];
	sTime.Hours=tmp1[3];
	sTime.Minutes=tmp1[4];
	sTime.Seconds=tmp1[5];
	HAL_RTC_SetDate(&hrtc,&DateToUpdate,RTC_FORMAT_BCD);
	HAL_RTC_SetTime(&hrtc,&sTime,RTC_FORMAT_BCD);
}

int flash_write(uint32_t *buf,int len)
{
	HAL_FLASH_Unlock();

  EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
  EraseInitStruct.PageAddress = 0x0800FC00;
  EraseInitStruct.NbPages     = 1;
	uint32_t PAGEError=0;
  if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK)
  {
		return 0;
  }
	uint32_t Address = 0x0800FC00;
	//uint32_t end=0x0800FC00+len;
  for(int t=0;t<len/4;t++)
  {
    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, (uint32_t )buf[t]) == HAL_OK)
    {
      Address = Address + 4;
    }
    else
    {
			return 0;
		}
	}
	HAL_FLASH_Lock();
	return 1;
}

void flash_read(uint32_t addr,uint8_t *buf,int len)
{
	uint32_t Address = 0x0800FC00+addr;
  for(uint16_t k=0;k<len;k++){
    buf[k] = *(__IO uint8_t *)Address;
    Address  ++;
  }
}

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
